﻿// 获取向量数据的函数
async function getVectorFromModel(word, modelName = 'm_wv_model2') {
    try {
        const response = await fetch(`http://localhost:5000/check_word?word=${encodeURIComponent(word)}&model=${modelName}`);
        if (!response.ok) {
            const errorData = await response.json();
            throw new Error(errorData.error || '获取向量失败');
        }
        return await response.json();
    } catch (error) {
        console.error('API 请求失败:', error);
        throw new Error('无法连接到服务器，请检查网络连接或服务是否启动');
    }
}

// 格式化并显示向量数据
function displayVector(data, targetId) {
    try {
        const vectorOutput = document.getElementById(targetId);
        vectorOutput.innerHTML = ''; // 清空现有内容

        if (data.in_vocabulary) {
            // 创建词汇信息
            const wordInfo = document.createElement('div');
            wordInfo.className = 'p-2 bg-blue-50 rounded mb-2';
            wordInfo.innerHTML = `
                <div class="font-semibold">词汇: <span class="text-blue-600">${data.word}</span></div>
                <div>向量维度: <span class="text-blue-600">${data.vector_dim}</span></div>
            `;
            vectorOutput.appendChild(wordInfo);

            // 创建向量数值显示
            const gridContainer = document.createElement('div');
            gridContainer.className = 'grid grid-cols-5 gap-1 text-xs';

            // 分批添加向量值，避免一次性渲染大量DOM元素导致卡顿
            const batchSize = 50;
            const totalBatches = Math.ceil(data.vector.length / batchSize);

            function renderBatch(batchIndex) {
                if (batchIndex >= totalBatches) return;

                const startIdx = batchIndex * batchSize;
                const endIdx = Math.min(startIdx + batchSize, data.vector.length);

                for (let i = startIdx; i < endIdx; i++) {
                    const valueDiv = document.createElement('div');
                    valueDiv.className = 'p-1 bg-gray-100 rounded text-center';
                    valueDiv.textContent = parseFloat(data.vector[i]).toFixed(6); // 保留6位小数
                    gridContainer.appendChild(valueDiv);
                }

                vectorOutput.appendChild(gridContainer);

                // 使用requestAnimationFrame优化渲染性能
                requestAnimationFrame(() => renderBatch(batchIndex + 1));
            }

            renderBatch(0);

            // 更新当前值和维度
            if (targetId === 'vector-list') {
                document.getElementById('current-values').textContent = data.vector.slice(0, 4).map(v => parseFloat(v).toFixed(6)).join(', ');
                document.getElementById('vector-dimension').textContent = data.vector_dim;
            }

            // 更新按钮文本
            const toggleButtonId = targetId === 'vector-list' ? 'toggle-vector-list' : 'toggle-vector-list2';
            const toggleButton = document.getElementById(toggleButtonId);
            toggleButton.innerHTML = `<i class="fa-solid fa-eye mr-1.5"></i>  展开${data.word} (${data.vector_dim}维) 向量`;
        } else {
            // 处理词汇不存在的情况
            const errorDiv = document.createElement('div');
            errorDiv.className = 'text-red-500 p-4';
            errorDiv.innerHTML = `
                <div class="flex items-start">
                    <div class="flex-shrink-0 pt-0.5"><i class="fa-solid fa-exclamation-triangle text-xl"></i></div>
                    <div class="ml-3">
                        <h3 class="text-lg font-medium text-red-800">词汇不存在</h3>
                        <div class="mt-2 text-sm text-red-700">${data.message}</div>
                    </div>
                </div>
            `;
            vectorOutput.appendChild(errorDiv);
        }

        // 添加脉冲动画
        const outputElement = document.getElementById('vector-output');
        outputElement.classList.add('animate-pulse');
        setTimeout(() => outputElement.classList.remove('animate-pulse'), 1000);
    } catch (error) {
        console.error('显示向量数据时出错:', error);
        throw error;
    }
}

// 显示提示消息
function showToast(message, type = 'success') {
    const toast = document.getElementById('toast');
    const toastMessage = document.getElementById('toast-message');

    // 重置toast样式
    toast.className = 'fixed bottom-5 right-5 text-white px-5 py-2.5 rounded-xl shadow-elevation-3 transform translate-y-20 opacity-0 transition-all duration-300 flex items-center z-50';

    // 设置消息内容和样式
    toastMessage.textContent = message;

    if (type === 'error') {
        toast.classList.add('bg-red-500');
    } else if (type === 'warning') {
        toast.classList.add('bg-yellow-500');
    } else {
        toast.classList.add('bg-gradient-to-r', 'from-green-500', 'to-teal-500');
    }

    // 显示toast
    toast.classList.remove('translate-y-20', 'opacity-0');

    // 自动隐藏
    setTimeout(() => {
        toast.classList.add('translate-y-20', 'opacity-0');
    }, 3000);
}

// 复制向量到剪贴板
function copyVectorToClipboard() {
    const vectorText = document.getElementById('vector-output').textContent;
    if (!vectorText.trim() || vectorText.includes('请在左侧输入单词')) {
        showToast('没有可复制的向量数据', 'error');
        return;
    }

    navigator.clipboard.writeText(vectorText)
       .then(() => showToast('向量已复制到剪贴板'))
       .catch(err => {
            console.error('复制失败:', err);
            showToast('复制失败，请重试', 'error');
        });
}

// 下载向量数据
function downloadVector() {
    const vectorText = document.getElementById('vector-output').textContent;
    if (!vectorText.trim() || vectorText.includes('请在左侧输入单词')) {
        showToast('没有可下载的向量数据', 'error');
        return;
    }

    const blob = new Blob([vectorText], { type: 'text/plain' });
    const a = document.createElement('a');
    a.download = `vector_${document.getElementById('word-input').value || 'unknown'}.txt`;
    a.href = URL.createObjectURL(blob);

    // 模拟点击下载
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(a.href);

    showToast('向量已下载');
}

// 绘制图表
function drawCharts(vectorDataList) {
    if (vectorDataList.length < 2) return; // 确保有两个向量数据
    const vector1 = vectorDataList[0].vector;
    const vector2 = vectorDataList[1].vector;

    // 转换数据格式以适应 chartjs-chart-heatmap 插件
    const heatmapData = [];
    vector1.forEach((value, index) => {
        heatmapData.push({ x: index, y: 0, v: value });
    });
    vector2.forEach((value, index) => {
        heatmapData.push({ x: index, y: 1, v: value });
    });


    // ------------------------- 散点图 -------------------------
    const scatterplotCtx = document.getElementById('scatterplot').getContext('2d');
    // 清空现有图表
    if (scatterplotCtx.chart) scatterplotCtx.chart.destroy();
    const scatterData = vector1.map((v, i) => ({ x: v, y: vector2[i] }));
    new Chart(scatterplotCtx, {
        type: 'scatter',
        data: {
            datasets: [{
                label: '向量对比',
                data: scatterData,
                backgroundColor: 'rgba(255, 99, 132, 0.5)',
                borderColor: 'rgba(255, 99, 132, 1)'
            }]
        },
        options: {
            responsive: true,
            scales: {
                x: {
                    title: { display: true, text: '向量1值' },
                    beginAtZero: false
                },
                y: {
                    title: { display: true, text: '向量2值' },
                    beginAtZero: false
                }
            }
        }
    });

    // ------------------------- 近似图（折线图） -------------------------
    const similarityplotCtx = document.getElementById('similarityplot').getContext('2d');
    if (similarityplotCtx.chart) similarityplotCtx.chart.destroy();
    new Chart(similarityplotCtx, {
        type: 'line',
        data: {
            labels: vector1.map((_, i) => `维度 ${i+1}`), // 更清晰的标签
            datasets: [{
                label: '向量1',
                data: vector1,
                borderColor: '#3b82f6',
                fill: false
            }, {
                label: '向量2',
                data: vector2,
                borderColor: '#0ea5e9',
                fill: false
            }]
        },
        options: {
            responsive: true,
            scales: {
                x: { title: { display: true, text: '向量维度' } },
                y: { title: { display: true, text: '向量值' } }
            }
        }
    });

     // ------------------------- 情感分析图（柱状图） -------------------------
    const sentimentplotCtx = document.getElementById('sentimentplot').getContext('2d');
    if (sentimentplotCtx.chart) sentimentplotCtx.chart.destroy();
    new Chart(sentimentplotCtx, {
        type: 'bar',
        data: {
            labels: ['向量1', '向量2'],
            datasets: [{
                label: '情感值总和',
                data: [vector1.reduce((a, b) => a + b, 0), vector2.reduce((a, b) => a + b, 0)],
                backgroundColor: ['#3b82f6', '#0ea5e9']
            }]
        },
        options: {
            responsive: true,
            scales: {
                y: { title: { display: true, text: '情感值总和' } }
            }
        }
    });
}

// 初始化事件监听
document.addEventListener('DOMContentLoaded', () => {
    const checkButton = document.getElementById('check-button');
    const copyButton = document.getElementById('copy-button');
    const downloadButton = document.getElementById('download-button');
    const wordInput = document.getElementById('word-input');
    const wordInput2 = document.getElementById('word-input2');
    const modelSelect = document.getElementById('model-select');
    const toggleVectorList = document.getElementById('toggle-vector-list');
    const toggleVectorList2 = document.getElementById('toggle-vector-list2');

    // 检查按钮点击事件
    checkButton.addEventListener('click', async () => {
        // .trim()：移除字符串首尾的空白字符（空格、换行符、制表符等）  类似python的.strip()
        const word = wordInput.value.trim();
        const word2 = wordInput2.value.trim();

        // 原始数据或对比数据为空时 清空对应的向量表示
        if (!word) {
            // innerHTML获取或设置 HTML 元素的内容
            document.getElementById('vector-list').innerHTML = '';
            toggleVectorList.innerHTML = `<i class="fa-solid fa-eye mr-1.5 text-lg"></i> 原始数据向量`;
        }
        if (!word2) {
            document.getElementById('vector-list2').innerHTML = '';
            toggleVectorList2.innerHTML = `<i class="fa-solid fa-eye mr-1.5 text-lg"></i> 对比数据向量`;
        }

        // 原始数据或对比数据均为空时 提示输入word
        if (!word && !word2) {
            showToast('请输入至少一个要检查的单词', 'warning');
            return;
        }

        try {
            // 显示加载状态
            checkButton.disabled = true;
            checkButton.innerHTML = '<i class="fa-solid fa-spinner fa-spin mr-2"></i> 处理中...';
            document.getElementById('processing-time').textContent = '--';

            // 记录开始时间
            const startTime = performance.now();

            const selectedModel = modelSelect.value;
            const promises = [];

            if (word) {
                promises.push(getVectorFromModel(word, selectedModel));
            }

            if (word2) {
                promises.push(getVectorFromModel(word2, selectedModel));
            }

            const vectorDataList = await Promise.all(promises);

            if (word) {
                displayVector(vectorDataList[0], 'vector-list');
            }

            if (word2) {
                displayVector(vectorDataList[word ? 1 : 0], 'vector-list2');
            }

            // 绘制图表
            drawCharts(vectorDataList);

            // 记录结束时间
            const endTime = performance.now();
            // 计算处理时间，保留两位小数
            const processingTime = (endTime - startTime).toFixed(2);
            // 显示处理时间
            document.getElementById('processing-time').textContent = `${processingTime} ms`;

            showToast('向量生成成功');
        } catch (error) {
            console.error('获取向量失败:', error);
            showToast(error.message, 'error');

            // 显示错误信息
            const errorHtml = `
                <div class="text-red-500 p-4">
                    <div class="flex items-start">
                        <div class="flex-shrink-0 pt-0.5"><i class="fa-solid fa-exclamation-triangle text-xl"></i></div>
                        <div class="ml-3">
                            <h3 class="text-lg font-medium text-red-800">获取向量失败</h3>
                            <div class="mt-2 text-sm text-red-700">${error.message}</div>
                        </div>
                    </div>
                </div>
            `;

            if (!word) {
                document.getElementById('vector-list').innerHTML = errorHtml;
            }
            if (!word2) {
                document.getElementById('vector-list2').innerHTML = errorHtml;
            }
        } finally {
            // 无论请求成功还是失败，都恢复按钮状态
            checkButton.disabled = false;
            checkButton.innerHTML = '<i class="fa-solid fa-calculator mr-2"></i> 获取向量表示';
            console.log('按钮状态已恢复');
        }
    });

    // 复制按钮点击事件
    copyButton.addEventListener('click', copyVectorToClipboard);

    // 下载按钮点击事件
    downloadButton.addEventListener('click', downloadVector);

    // 回车键触发检查
    wordInput.addEventListener('keypress', (e) => {
        if (e.key === 'Enter') {
            checkButton.click();
        }
    });

    wordInput2.addEventListener('keypress', (e) => {
        if (e.key === 'Enter') {
            checkButton.click();
        }
    });

    // 添加页面加载动画
    document.body.classList.add('opacity-0');
    setTimeout(() => {
        document.body.classList.add('transition-opacity', 'duration-700');
        document.body.classList.remove('opacity-0');
    }, 100);

    // 初始化显示
    const initialMessage = `
        <div class="text-gray-500 p-4 text-center">
            <div class="mb-2"><i class="fa-solid fa-info-circle text-xl"></i></div>
            <div class="text-sm">请在左侧输入单词并点击"获取向量表示"按钮</div>
        </div>
    `;
    document.getElementById('vector-list').innerHTML = initialMessage;
    document.getElementById('vector-list2').innerHTML = '';

    // 处理显示/隐藏向量按钮的点击事件
    toggleVectorList.addEventListener('click', () => {
        const vectorList = document.getElementById('vector-list');
        if (vectorList.style.display === 'none') {
            vectorList.style.display = 'block';
        } else {
            vectorList.style.display = 'none';
        }
    });

    toggleVectorList2.addEventListener('click', () => {
        const vectorList2 = document.getElementById('vector-list2');
        if (vectorList2.style.display === 'none') {
            vectorList2.style.display = 'block';
        } else {
            vectorList2.style.display = 'none';
        }
    });
});